package com.hongyi.websocket.handler;

import com.hongyi.common.framework.domain.LoginUser;
import com.hongyi.common.framework.utils.common.CollectionUtils;
import com.hongyi.websocket.domain.WebSocketMessageDto;
import com.hongyi.websocket.holder.WebSocketSessionHolder;
import com.hongyi.websocket.utils.WebSocketUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.util.List;

import static com.hongyi.common.framework.constant.WebSocketConstants.LOGIN_USER_KEY;


/**
 * WebSocketHandler 实现类
 *
 * <p>用于处理WebSocket连接的各种事件和消息</p>
 * @author DingHao
 */
@Slf4j
public class LyWebSocketHandler extends AbstractWebSocketHandler {

    /**
     * 连接成功后
     *
     * <p>当客户端与服务器端建立连接后，会触发该方法</p>
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
        //将用户的userId与session关联起来，存储在一个静态或全局管理器WebSocketSessionHolder中，以便后续可以查找特定用户的会话
        WebSocketSessionHolder.addSession(loginUser.getUserId(), session);
        log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType());
    }

    /**
     * 处理发送来的文本消息
     *
     * <p>将用户的userId与session关联起来，存储在一个静态或全局管理器WebSocketSessionHolder中，以便后续可以查找特定用户的会话</p>
     * @param session 当前连接的WebSocketSession
     * @param message 发送的文本消息
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
        List<Long> userIds =  CollectionUtils.newArrayList(loginUser.getUserId());
        //创建一个WebSocketMessageDto对象来封装消息内容和发送者的userId
        WebSocketMessageDto webSocketMessage = new WebSocketMessageDto();
        webSocketMessage.setSessionKeys(userIds);
        webSocketMessage.setMessage(message.getPayload());
        //发布消息
        WebSocketUtils.publishMessage(webSocketMessage);
    }

    /**
     * 接收到二进制消息时，这个方法会被调用
     *
     * <p>调用了父类的方法处理二进制消息</p>
     */
    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
        super.handleBinaryMessage(session, message);
    }

    /**
     * 心跳监测的回复
     *
     * @param session 当前连接的WebSocketSession
     * @param message 文本消息
     * @throws Exception
     */
    @Override
    protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
        //调用WebSocketUtils.sendPongMessage(session)来响应心跳，确保连接保持活动状态
        WebSocketUtils.sendPongMessage(session);
    }

    /**
     * 连接出错时
     *
     * <p>当连接出现错误时，会触发该方法</p>
     * @param session 当前连接的WebSocketSession
     * @param exception 异常信息
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("[transport error] sessionId: {} , exception:{}", session.getId(), exception.getMessage());
    }

    /**
     * 连接关闭后
     *
     * <p>当连接关闭后，会触发该方法</p>
     * @param session 当前连接的WebSocketSession
     * @param status
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
        //从WebSocketSessionHolder中移除与用户userId相关的session
        WebSocketSessionHolder.removeSession(loginUser.getUserId());
        log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType());
    }

    /**
     * 是否支持分片消息
     *
     * @return
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

}
